package com.example.nfcaccesssystem;

import java.util.ArrayList;
import java.util.HashMap;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

//This is the controller singleton
public final class Controller {
	
	private static Controller instance = null;
	
	// A reference to the UserActivity for the callback
	private UserActivity userAc = null;
	// A reference to the DoorActivity for the callback
	private DoorActivity doorAc = null;
	// A reference to the EditDoorActivity for the callback
	private EditDoorActivity editDoorAc = null;
	// A reference to the NewDoorActivity for the callback
	private NewDoorActivity newDoorAc = null;
	// A reference to the NewUserActivity for the callback
	private NewUserActivity newUserAc = null;
	// A reference to the EditUserActivity for the callback
	private EditUserActivity editUserAc = null;
	
	//Hold an updated list of users and doors which can be used as adapters for listviews.
	ArrayList<User> userList = new ArrayList<User>();
	ArrayList<Door> doorList = new ArrayList<Door>();
	
	//Hold an updated map of who has access to which doors which can be used for multiple select listviews.
	HashMap<User, Boolean> doorAccessMap = new HashMap<User, Boolean>();
	HashMap<Door, Boolean> userAccessMap = new HashMap<Door, Boolean>();
	
	//Only access to the model through the interface. This is done to have a loose coupling to the model.
	//And we know that there is only created one model object and therefore only one connection to the server.
	private IModel model;

	
	
	private Controller(){
		model = new Model();
	}
	
	public static Controller getInstance(){
		if (instance == null) {
            instance = new Controller();
        }
        return instance;
	}
	
	public void getUsers(UserActivity ac) {
		
		if(userAc == null || !userAc.equals(ac)) {
			userAc = ac;
		}
		
		model.getUsers();
	}
	
	public void getUsers() {
		
		model.getUsers();
	}
	
	public void createUser(NewUserActivity ac, String name, String accessId, Door[] doorArray){
		if(newUserAc == null || !newUserAc.equals(ac)) {
			newUserAc = ac;
		}
		model.createUser(name, accessId, doorArray);
	}
	
	public void createDoor(NewDoorActivity ac, String newDoorInfo, User[] userArray) {
		if(newDoorAc == null || !newDoorAc.equals(ac)) {
			newDoorAc = ac;
		}
		model.createDoor(newDoorInfo, userArray);
		
	}
	
	public void deleteDoor(int id) {
		
		model.deleteDoor(id);
	}

	public void deleteUser(int id) {
		
		model.deleteUser(id);
	}
	
	public void getDoors(DoorActivity ac){
		
		if(doorAc == null || !doorAc.equals(ac)) {
			doorAc = ac;
		}
		
		model.getDoors();
	}

	public void getUsersAndAccess(Door d, EditDoorActivity ac) {
		
		if (editDoorAc == null || !editDoorAc.equals(ac)) {
			editDoorAc = ac;
		}
		
		model.getUsersAndAccess(d);
	}
	
	public void getDoorsAndAccess(User u, EditUserActivity ac) {
		
		if (editUserAc == null || !editUserAc.equals(ac)) {
			editUserAc = ac;
		}
		
		model.getDoorsAndAccess(u);
	}

	public void addUserDoorAccess(User u, Door d){
		
		model.addUserDoorAccess(u, d);
	}

	public void removeUserDoorAccess(User u, Door d) {
		
		model.removeUserDoorAccess(u, d);
	}
	
	public void changeDoorInfo(int id, String info) {
		
		model.changeDoorInfo(id, info);
	}
	
	public void changeUserName(int id, String name) {
		
		model.changeUserName(id, name);
	}
	
	public void changeUserAccessId(int id, String accessId) {
		
		model.changeUserAccessId(id, accessId);
	}

	public void setUsers(String response) {
		
		JSONObject jsonObj = null;
        
		User[] users = null;
		
        try {
        	userList.clear();
        	
			jsonObj = new JSONObject(response);
		
	        JSONArray jsonArray = null;
	        
			jsonArray = jsonObj.getJSONArray("users");
			
	        users = new User[jsonArray.length()];
		
	        for(int i = 0; i < jsonArray.length(); i++) {
	        	User newUser = new User(jsonArray.getJSONObject(i).getString("name"), Integer.parseInt(jsonArray.getJSONObject(i).getString("id")), jsonArray.getJSONObject(i).getString("accessid"));
	        	users[i] = newUser;
	        }
        } 
        catch (JSONException jex){
        	// Catch exception if a JSON exception occurs.
        	jex.printStackTrace();
        }
		userAc.setUsers(users);
	}
	
	public void setDoors(String response) {
		
		JSONObject jsonObj = null;
        
		Door[] doors = null;
		
        try {
        	doorList.clear();
        	
			jsonObj = new JSONObject(response);
		
	        JSONArray jsonArray = null;
	        
			jsonArray = jsonObj.getJSONArray("doors");
			
	        doors = new Door[jsonArray.length()];
			
	        for(int i = 0; i < jsonArray.length(); i++) {
	        	Door newDoor = new Door(jsonArray.getJSONObject(i).getString("doorInfo"), Integer.parseInt(jsonArray.getJSONObject(i).getString("id")));
	        	doors[i] = newDoor;
	        }
        
        }
        catch (JSONException jex){
        	// Catch exception if a JSON exception occurs.
        	jex.printStackTrace();
        }
		
        doorAc.setDoors(doors);
	}
	
	public void setUsersAndAccess(String response) {
		
		JSONObject jsonObj = null;
		
		doorAccessMap.clear();
		
		try {
			
			jsonObj = new JSONObject(response);
		
	        JSONArray jsonArray = jsonObj.getJSONArray("useraccess");
	       
	        for(int i = 0; i < jsonArray.length(); i++) {
	        	User newUser = new User(jsonArray.getJSONObject(i).getString("name"), Integer.parseInt(jsonArray.getJSONObject(i).getString("id")), jsonArray.getJSONObject(i).getString("accessid"));
	        	String accessString = jsonArray.getJSONObject(i).getString("access");
	        	boolean access = Boolean.parseBoolean(accessString);
	        	
	        	//Insert access into map
	        	doorAccessMap.put(newUser, access);
	        }
		}
        catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
        }
		
		editDoorAc.setUsersAndAccess();
		
	}
	
	public void setDoorsAndAccess(String response) {
		
		JSONObject jsonObj = null;
		
		userAccessMap.clear();
		
		try {
			
			jsonObj = new JSONObject(response);
		
	        JSONArray jsonArray = jsonObj.getJSONArray("dooraccess");
	        Log.i("User Access Rights", jsonArray.toString());
	        for(int i = 0; i < jsonArray.length(); i++) {
	        	Door newDoor = new Door(jsonArray.getJSONObject(i).getString("info"), Integer.parseInt(jsonArray.getJSONObject(i).getString("id")));
	        	String accessString = jsonArray.getJSONObject(i).getString("access");
	        	boolean access = Boolean.parseBoolean(accessString);
	        	
	        	//Insert access into map
	        	userAccessMap.put(newDoor, access);
	        }
		}
        catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
        }
		
		editUserAc.setDoorsAndAccess();
		
	}
	
	public void setUsersDoorAccess(boolean response) {
		editDoorAc.setUsersDoorAccess(response);
	}
	
	public void setDoorsUserAccess(boolean response) {
		editUserAc.setDoorsUserAccess(response);
	}
	
	public void setNewDoor(boolean response) {
		newDoorAc.setNewDoor(response);
	}
	
	public void setNewUser(boolean response) {
		newUserAc.setNewUser(response);
	}

	public void setDeleteNewDoor(boolean response) {
		editDoorAc.setDeleteNewDoor(response);
	}
	
	public void setDeleteNewUser(boolean response) {
		editUserAc.setDeleteNewUser(response);
	}
	
	public int getNumberOfUsers(){
		return userList.size();
	}
}
